package com.mpsc.singleton.demo.handler.ws;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint(value = "/online/{taskType}")
public class TaskStatusWebSocket {

    /**
     * 日志记录
     */
    private static final Logger LOG = LoggerFactory.getLogger(TaskStatusWebSocket.class);

    /**
     * 在线列表
     */
    private static ConcurrentHashMap<String, CopyOnWriteArraySet<TaskStatusWebSocket>> ONLINE_LIST = new ConcurrentHashMap<>();

    /**
     * 会话信息
     */
    private Session session;

    /**
     * ｛建立连接｝
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "taskType") String taskType) {
        LOG.info("建立连接：{},任务类型：{}", session.getId(), taskType);
        this.session = session;
        CopyOnWriteArraySet<TaskStatusWebSocket> sessionList = ONLINE_LIST.getOrDefault(taskType, new CopyOnWriteArraySet<>());
        sessionList.add(this);
        ONLINE_LIST.put(taskType, sessionList);
    }

    /**
     * 处理客户端发送的消息
     */
    @OnMessage
    public void onMessage(Session session, String message, @PathParam(value = "taskType") String taskType) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("消息连接：{}, 任务类型：{}, 消息信息：{}", session.getId(), taskType, message);
        }
        // TODO 消息处理
    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose(@PathParam(value = "taskType") String taskType) throws IOException {
        LOG.info("关闭连接：{},任务ID：{}", session.getId(), taskType);
        CopyOnWriteArraySet<TaskStatusWebSocket> sessionList = ONLINE_LIST.getOrDefault(taskType, new CopyOnWriteArraySet<>());
        sessionList.remove(this);
        this.session.close();
    }

    /**
     * 发生错误
     */
    @OnError
    public void onError(Session session, Throwable error, @PathParam(value = "taskType") String taskType) {
        LOG.error("异常连接：{},任务连接{},异常信息：{}", session.getId(), taskType, error.getMessage());
        // 发生错误进行连接去除
        CopyOnWriteArraySet<TaskStatusWebSocket> sessionList = ONLINE_LIST.getOrDefault(taskType, new CopyOnWriteArraySet<>());
        sessionList.remove(this);
        try {
            this.session.close();
        } catch (Exception e) {
            LOG.error("因异常：{}，关闭 WS 发生错误，错误信息：{}", error, e.getMessage(), e);
        }
    }

    /**
     * ｛发送客户端消息｝
     */
    public static void sendMsgToClient(String msg, String taskType) {
        CopyOnWriteArraySet<TaskStatusWebSocket> sessions = ONLINE_LIST.get(taskType);
        if (null == sessions || sessions.size() == 0) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("当前用户ID：{}并无会话建立，不进行消息发送！", taskType);
            }
        } else {
            for (TaskStatusWebSocket remote : sessions) {
                try {
                    remote.sendMsg(msg);
                } catch (Exception e) {
                    LOG.error("主动给客户端发送消息异常，用户 ID：{}，异常信息：{}", taskType, e.getMessage(), e);
                }
            }
        }
    }

    /**
     * ｛发送消息｝
     */
    public void sendMsg(String msg) throws IOException {
        if (Objects.nonNull(this.session) && this.session.isOpen()) {
            synchronized (this.session) {
                this.session.getBasicRemote().sendText(msg);
            }
        }
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

}
